TAB0 =
TAB1 = ``t
ENTER0 =
ENTER1 = ``n
SPACE0 =
SPACE1 :=" "

P(s, snd){
s:=myESC(s)
StringSplit, wds, s, "^|"
s1:=myUnESC(wds1) 
s2:=myUnESC(wds2)
s:=s1 . s2
clip := ClipboardAll 
;while clipboard <>
;{
;  clipboard = 
;}
Clipboard = %s%
clipwait
;Sleep 1
if clipboard <>
{
send ^v
i:=StrLen(s2)
sendinput, {left %i%}
if snd
  SoundPlay min.wav
 }
;sleep 100
Clipboard:=clip
clip=
Return
}

myESC(s){
StringReplace, s, s, \|, 97e8cd29c8c56ed7fe56ed46865fc2c8, 1
StringReplace, s, s, \^, 28d397e87306b8631f3ed80d858d35f0, 1
StringReplace, s, s, ", d41d8cd98f00b204e9800998ecf8427e, 1
return s
}

myUnESC(s){
StringReplace, s, s, 97e8cd29c8c56ed7fe56ed46865fc2c8, |, 1
StringReplace, s, s, 28d397e87306b8631f3ed80d858d35f0, ^, 1
StringReplace, s, s, d41d8cd98f00b204e9800998ecf8427e, ", 1
return s
}

WM_MOUSEMOVE()
{
    static CurrControl, PrevControl, _TTip  ; _TT is kept blank for use by the ToolTip command below.
    CurrControl := A_GuiControl
    
    IfInString CurrControl, & 
    {
      StringReplace, CurrControl, CurrControl, &,,all
    }
    if !RegExMatch(CurrControl, "^[A-z]")
    {
      CurrControl = undefined
    }
    If (CurrControl <> PrevControl and not InStr(CurrControl, " "))
    {
        ToolTip  ; Turn off any previous tooltip.
        SetTimer, DisplayToolTip, 1000
        PrevControl := CurrControl
    }
    return

    DisplayToolTip:
    SetTimer, DisplayToolTip, Off
    ToolTip % %CurrControl%_TTip  ; The leading percent sign tell it to use an expression.
    SetTimer, RemoveToolTip, 3000
    return

    RemoveToolTip:
    SetTimer, RemoveToolTip, Off
    ToolTip
    return
}

today(){
 FormatTime today
 return today
}

sepTo2(string, sepchar = "_") ; separate it to 2 parts
{
  StringGetPos , pos, string, %sepchar%, R
  StringLeft, lstr, string, pos
  StringRight, rstr, string, StrLen(string)-Pos-1
  r :=[lstr, rstr]
  return r
}

ifContain(array, value) ;test if an array contains a value; if it contains, return the index of the first occurrence of the value; other, return 0
{
  for i, v in array
  {
    if  Distance(v, value) = 0
    ;if v == %value%
      return i
  }
  return 0
}

flat(array, d = "`n") ; flat an array of strings into a comma (or any other char) separated string list
{
  s =
  for i, v in array
  {
    s := s . v . d
  }
  l := StrLen(s) - 1
  StringLeft s, s, l  ;msgbox % s
  return s
}

dedup(ByRef array) ;sort and deduplicate a string array
{
  s := flat(array)
  sort, s, CU
  StringSplit, a, s, `n
  aa := Array()
  loop %a0%
  {
    aa.Insert(a%A_Index%)
  }
  array := aa
  return array
}

Distance(string1, string2, maxOffset=5) {
  StringSplit, n, string1
  StringSplit, m, string2
  IfEqual n0,0, Return m0
  IfEqual m0,0, Return n0
  c = 1
  offset1 = 0
  offset2 = 0
  lcs = 0
  While((c + offset1 <= n0) && (c + offset2 <= m0)) {
    ni := c + offset1
    mi := c + offset2
    If (n%ni% == m%mi%)
      lcs++
    else{
      offset1 = 0
      offset2 = 0
      Loop, % maxOffset  {
        oi := c + A_Index
        if ((oi < n0) && (n%oi% == m%c%)) {
            offset1 := A_Index
            break
        }
        if ((oi < m0) && (n%c% == m%oi%)) {
            offset2 := A_Index
            break
        }
      }
    }
    c++
  }
  Return (n0 + m0)/2 - lcs
}

ifEQ(a, b){
  tf := Distance(a, b)?false:true
  return tf
}

arrayToString(arry){ ; to string like ["a","b","c"...]
  s =
  for i,v in arry
  {
    s = %s%"%v%",
  }
  stringleft ,s,s, StrLen(s)-1
  return s
}

GetIME(ByRef out_LayOut)
{
  SetFormat, integer, hex
  HKL:=DllCall("GetKeyboardLayout","int",GetThread(),UInt) 
  StringTrimLeft,Layout,HKL,2
  Layout:= HKL=0x8040804 ? "00000804" : Layout
  Layout:= HKL=0x4090409 ? "00000409" : Layout 
  out_LayOut:=Layout
  return out_Layout
}

GetThread()
{
  ResultID:=0
  hWnd:=WinExist("A")
  VarSetCapacity( thE, 28, 0 )
  NumPut( 28, thE )
  WinGet,processID,pid,ahk_id %hWnd%
  hProcessSnap := DllCall("CreateToolhelp32Snapshot","uint",4, "uint",processID)
  If (DllCall("Thread32First","uint",hProcessSnap, "uint",&thE )=0)
  {
    Return 0
  }

  Loop
  {
    If (NumGet(thE,12) = processID)
    {
      DllCall("CloseHandle","uint",hProcessSnap)
      ResultID:=NumGet(thE,8)
      Return ResultID
    }
    NumPut( 28, thE )
    if( DllCall("Thread32Next","uint",hProcessSnap, "uint",&thE )=0)
    { 
      DllCall("CloseHandle","uint",hProcessSnap)
      Return 0
    }
  } 
}

SwitchIME(dwLayout)
{
  HKL:=DllCall("LoadKeyboardLayout", Str, dwLayout, UInt, 1)
  ControlGetFocus,ctl,A
  SendMessage,0x50,0,HKL,%ctl%,A
}

sendWithoutIME(str)
{
  StringReplace , str, str, `, ``, All
  current_layout := GetIME(layout)
  switchIME("00000409")
  SendInput, {Raw}%str%
  switchIME(current_layout)
  return
}

S(s, snd)
{
  s:=myESC(s)
  StringSplit, wds, s, "^|"
  s1:=myUnESC(wds1)  
  s2:=myUnESC(wds2)
  s:=s1 . s2
  sendWithoutIME(s)
  i:=StrLen(s2)
  sendinput, {left %i%}
  if snd
    SoundPlay min.wav
  return
}